#!/usr/bin/python
import unittest
import os
import sys
import shutil

class testModules(unittest.TestCase):
    """
    Module test class for the pipe tool.
    """
    testPath = None

    def runCmd(self, cmd, args):
        newCmd = '%s %s > "%s"' % (os.path.join('.', cmd), args,
                                   self.resultFile)
        os.system(newCmd)

    def remove_test_dir(self):
        if os.path.exists(self.testDir):
            shutil.rmtree(self.testDir)

    def setUp(self):
        if not testModules.testPath:
            testModules.testPath = os.path.abspath(os.path.dirname(__file__))

        os.chdir(self.testPath)

        testModules.resultFile = os.path.join(testModules.testPath,
                                              'result.log')
        if os.path.exists(self.resultFile):
            os.remove(self.resultFile)

        self.testDir = os.path.join(testModules.testPath, "test dir")
        self.remove_test_dir()
        os.makedirs(self.testDir)
        self.makeTestFile("testfile1.txt", "a")
        self.makeTestFile("testfile2.txt", "b")
        os.chdir("..")

    def tearDown(self):
        self.remove_test_dir()

    def makeTestFile(self, name, addition):
        fName = os.path.join(self.testDir, name)
        f = open(fName, "w")
        for i in xrange(10):
            f.write("test line %d %s\n" % (i, addition))
        f.close()

    def getResultLog(self):
        f = None
        try:
            f = open(self.resultFile)
            return f.readlines()
        finally:
            if f:
                f.close()

    def inResults(self, theLine):
        result = self.getResultLog()
        foundIt = False

        for line in result:
            if line.find(theLine) != -1:
                foundIt = True

        return foundIt

    def printResults(self):
        result = self.getResultLog()
        for line in result:
            self.printErr(line)

    def print_err(self, *args):
        sys.stderr.write(" ".join([str(line) for line in args]))

    def print_err_line(self, *args):
        sys.stderr.write(" ".join([str(line) for line in args]) + os.linesep)

    def test_Write_File_Names_With_Files_Parameter(self):
        self.runCmd('pipe.py', '-t txt "test line 1" -f')

        result = self.getResultLog()

        file1_found = False
        file2_found = False

        for line in result:
            if line.find('testfile1.txt') != -1:
                file1_found = True

            if line.find('testfile2.txt') != -1:
                file2_found = True

        self.assertTrue(file1_found)
        self.assertTrue(file2_found)
        self.assertEqual(2, len(result))

    def test_Custom_Execute_With_Exe_Parameter(self):
        self.runCmd('pipe.py', '-t txt "test line 1" --exe "print \'CUSTOM\', '
                               'kwargs[\'line\'],"')

        result = self.getResultLog()

        line1Found = False
        line2Found = False

        for line in result:
            if line.find('CUSTOM test line 1 a') != -1:
                line1Found = True

            if line.find('CUSTOM test line 1 b') != -1:
                line2Found = True

        self.assertTrue(line1Found)
        self.assertTrue(line2Found)
        self.assertEqual(2, len(result))

    def test_Remove_Line(self):
        self.runCmd('pipe.py', '-t txt "test line 5" --remove')

        result = self.getResultLog()

        found4 = False
        found5 = False
        found6 = False
        for line in result:
            if line.find('test line 4') != -1:
                found4 = True

            if line.find('test line 5') != -1:
                found5 = True

            if line.find('test line 6') != -1:
                found6 = True

        self.assertTrue(found4)
        self.assertFalse(found5)
        self.assertTrue(found6)

    def test_Select_Line(self):
        self.runCmd('pipe.py', '-t txt "test line 5"')

        result = self.getResultLog()

        found4 = False
        found5 = False
        found6 = False
        for line in result:
            if line.find('test line 4') != -1:
                found4 = True

            if line.find('test line 5') != -1:
                found5 = True

            if line.find('test line 6') != -1:
                found6 = True

        self.assertFalse(found4)
        self.assertTrue(found5)
        self.assertFalse(found6)

    def test_Select_Block(self):
        self.runCmd('pipe.py', '-t txt "test line 4" -e "test line 6"')

        result = self.getResultLog()

        found3a = False
        found4a = False
        found5a = False
        found6a = False
        found7a = False
        found3b = False
        found4b = False
        found5b = False
        found6b = False
        found7b = False

        for line in result:
            if line.find('test line 3 a') != -1:
                found3a = True

            if line.find('test line 4 a') != -1:
                found4a = True

            if line.find('test line 5 a') != -1:
                found5a = True

            if line.find('test line 6 a') != -1:
                found6a = True

            if line.find('test line 7 a') != -1:
                found7a = True

            if line.find('test line 3 b') != -1:
                found3b = True

            if line.find('test line 4 b') != -1:
                found4b = True

            if line.find('test line 5 b') != -1:
                found5b = True

            if line.find('test line 6 b') != -1:
                found6b = True

            if line.find('test line 7 b') != -1:
                found7b = True

        self.assertFalse(found3a)
        self.assertTrue(found4a)
        self.assertTrue(found5a)
        self.assertTrue(found6a)
        self.assertFalse(found7a)
        self.assertFalse(found3b)
        self.assertTrue(found4b)
        self.assertTrue(found5b)
        self.assertTrue(found6b)
        self.assertFalse(found7b)

    def test_Remove_Block(self):
        self.runCmd('pipe.py', '-t txt "test line 4" -e "test line 6" --remove')

        result = self.getResultLog()

        found3a = False
        found4a = False
        found5a = False
        found6a = False
        found7a = False
        found3b = False
        found4b = False
        found5b = False
        found6b = False
        found7b = False

        for line in result:
            if line.find('test line 3 a') != -1:
                found3a = True

            if line.find('test line 4 a') != -1:
                found4a = True

            if line.find('test line 5 a') != -1:
                found5a = True

            if line.find('test line 6 a') != -1:
                found6a = True

            if line.find('test line 7 a') != -1:
                found7a = True

            if line.find('test line 3 b') != -1:
                found3b = True

            if line.find('test line 4 b') != -1:
                found4b = True

            if line.find('test line 5 b') != -1:
                found5b = True

            if line.find('test line 6 b') != -1:
                found6b = True

            if line.find('test line 7 b') != -1:
                found7b = True

        self.assertTrue(found3a)
        self.assertFalse(found4a)
        self.assertFalse(found5a)
        self.assertFalse(found6a)
        self.assertTrue(found7a)
        self.assertTrue(found3b)
        self.assertFalse(found4b)
        self.assertFalse(found5b)
        self.assertFalse(found6b)
        self.assertTrue(found7b)

    def test_Remove_Block_Inplace(self):
        self.runCmd('pipe.py', '-t txt "test line 4" -e "test line 6" '\
                    '--remove --inplace')

        result = []
        for name in os.listdir(self.testDir):
            left, ext = os.path.splitext(name)

            if ext != ".txt":
                continue

            fileName = os.path.join(self.testDir, name)

            f = open(fileName)
            result += f.readlines()
            f.close()

        found3a = False
        found4a = False
        found5a = False
        found6a = False
        found7a = False
        found3b = False
        found4b = False
        found5b = False
        found6b = False
        found7b = False

        for line in result:
            if line.find('test line 3 a') != -1:
                found3a = True

            if line.find('test line 4 a') != -1:
                found4a = True

            if line.find('test line 5 a') != -1:
                found5a = True

            if line.find('test line 6 a') != -1:
                found6a = True

            if line.find('test line 7 a') != -1:
                found7a = True

            if line.find('test line 3 b') != -1:
                found3b = True

            if line.find('test line 4 b') != -1:
                found4b = True

            if line.find('test line 5 b') != -1:
                found5b = True

            if line.find('test line 6 b') != -1:
                found6b = True

            if line.find('test line 7 b') != -1:
                found7b = True

        self.assertTrue(found3a)
        self.assertFalse(found4a)
        self.assertFalse(found5a)
        self.assertFalse(found6a)
        self.assertTrue(found7a)
        self.assertTrue(found3b)
        self.assertFalse(found4b)
        self.assertFalse(found5b)
        self.assertFalse(found6b)
        self.assertTrue(found7b)

    def test_Remove_Block_New_File(self):
        self.runCmd('pipe.py', '-t txt "test line 4" -e "test line 6" --remove '\
                               '--newfile')

        result = []
        for name in os.listdir(self.testDir):
            left, ext = os.path.splitext(name)

            if ext != ".txt":
                continue

            if left.find("out1") == -1:
                continue

            fileName = os.path.join(self.testDir, name)

            f = open(fileName)
            result += f.readlines()
            f.close()

        found3a = False
        found4a = False
        found5a = False
        found6a = False
        found7a = False
        found3b = False
        found4b = False
        found5b = False
        found6b = False
        found7b = False

        for line in result:
            if line.find('test line 3 a') != -1:
                found3a = True

            if line.find('test line 4 a') != -1:
                found4a = True

            if line.find('test line 5 a') != -1:
                found5a = True

            if line.find('test line 6 a') != -1:
                found6a = True

            if line.find('test line 7 a') != -1:
                found7a = True

            if line.find('test line 3 b') != -1:
                found3b = True

            if line.find('test line 4 b') != -1:
                found4b = True

            if line.find('test line 5 b') != -1:
                found5b = True

            if line.find('test line 6 b') != -1:
                found6b = True

            if line.find('test line 7 b') != -1:
                found7b = True

        self.assertTrue(found3a)
        self.assertFalse(found4a)
        self.assertFalse(found5a)
        self.assertFalse(found6a)
        self.assertTrue(found7a)
        self.assertTrue(found3b)
        self.assertFalse(found4b)
        self.assertFalse(found5b)
        self.assertFalse(found6b)
        self.assertTrue(found7b)

    def test_Replace_In_Line(self):
        self.runCmd('pipe.py',
                    '-t txt "test.*5" --replacee "e" --replacer "EEE"')

        result = self.getResultLog()

        found4a = False
        found4b = False
        found5a = False
        found5b = False
        found6a = False
        found6b = False

        foundEEEa = False
        foundEEEb = False

        for line in result:
            if line.find('test line 4 a') != -1:
                found4a = True

            if line.find('test line 5 a') != -1:
                found5a = True

            if line.find('test line 6 a') != -1:
                found6a = True

            if line.find('test line 4 b') != -1:
                found4b = True

            if line.find('test line 5 b') != -1:
                found5b = True

            if line.find('test line 6 b') != -1:
                found6b = True

            if line.find('tEEEst linEEE 5 a') != -1:
                foundEEEa = True

            if line.find('tEEEst linEEE 5 b') != -1:
                foundEEEb = True

        self.assertTrue(found4a)
        self.assertFalse(found5a)
        self.assertTrue(found6a)
        self.assertTrue(found4b)
        self.assertFalse(found5b)
        self.assertTrue(found6b)
        self.assertTrue(foundEEEa)
        self.assertTrue(foundEEEb)

    def test_Replace_In_Line_Without_Replacee(self):
        self.runCmd('pipe.py', '-t txt "test.*5" --replacer "EEE"')

        result = self.getResultLog()

        found4a = False
        found4b = False
        found5a = False
        found5b = False
        found6a = False
        found6b = False

        foundEEEa = False
        foundEEEb = False

        for line in result:
            if line.find('test line 4 a') != -1:
                found4a = True

            if line.find('test line 5 a') != -1:
                found5a = True

            if line.find('test line 6 a') != -1:
                found6a = True

            if line.find('test line 4 b') != -1:
                found4b = True

            if line.find('test line 5 b') != -1:
                found5b = True

            if line.find('test line 6 b') != -1:
                found6b = True

            if line.find('EEE a') != -1:
                foundEEEa = True

            if line.find('EEE b') != -1:
                foundEEEb = True

        self.assertTrue(found4a)
        self.assertFalse(found5a)
        self.assertTrue(found6a)
        self.assertTrue(found4b)
        self.assertFalse(found5b)
        self.assertTrue(found6b)
        self.assertTrue(foundEEEa)
        self.assertTrue(foundEEEb)

    def test_Find_Any_File(self):
        self.runCmd('pipe.py', '"test" --fnd -t txt')

        result = self.getResultLog()

        found1 = False
        found2 = False

        for line in result:
            if line.find('testfile1.txt') != -1:
                found1 = True

            if line.find('testfile2.txt') != -1:
                found2 = True

        self.assertTrue(found1)
        self.assertTrue(found2)

    def test_Find_Any_File_With_Dirs(self):
        self.runCmd('pipe.py', '--fnd "test.dir" --all --dirs')

        result = self.getResultLog()

        found = False

        for line in result:
            if line.find('test dir') != -1:
                found = True

        self.assertTrue(found)

    def test_Shun_File_Names(self):
        self.runCmd('pipe.py', '"test" -t txt -f -s 1')

        result = self.getResultLog()

        found1 = False
        found2 = False

        for line in result:
            if line.find('testfile1.txt') != -1:
                found1 = True

            if line.find('testfile2.txt') != -1:
                found2 = True

        self.assertFalse(found1)
        self.assertTrue(found2)

        self.runCmd('pipe.py', '"test" -t txt -f -s 2')

        result = self.getResultLog()

        found1 = False
        found2 = False

        for line in result:
            if line.find('testfile1.txt') != -1:
                found1 = True

            if line.find('testfile2.txt') != -1:
                found2 = True

        self.assertTrue(found1)
        self.assertFalse(found2)


        self.runCmd('pipe.py', '"test" -t txt -f -s 1 -s 2')

        result = self.getResultLog()

        found1 = False
        found2 = False

        for line in result:
            if line.find('testfile1.txt') != -1:
                found1 = True

            if line.find('testfile2.txt') != -1:
                found2 = True

        self.assertFalse(found1)
        self.assertFalse(found2)

    def test_Select_Multi_Regex(self):
        self.runCmd('pipe.py', '"1.*a" "3.*a" "5.*a" -t txt --nocolor')

        result = self.getResultLog()

        found1a = False
        found3a = False
        found5a = False

        for line in result:
            if line.find('test line 1 a') != -1:
                found1a = True

            if line.find('test line 3 a') != -1:
                found3a = True

            if line.find('test line 5 a') != -1:
                found5a = True

        self.assertTrue(found1a)
        self.assertTrue(found3a)
        self.assertTrue(found5a)

    def test_Word_Count(self):
        self.runCmd('pipe.py', '--wc -t txt "test line 3" "test line 5"')

        result = self.getResultLog()
        self.assertTrue(result[0] == '      4      16      56\n')

    def test_Filter_File_Size(self):
        name = os.path.join(self.testDir, "small.sze")
        f = open(name, "w")
        for i in xrange(100):
            f.write("test line %d a\n" % i)
        f.close()

        name = os.path.join(self.testDir, "big.sze")
        f = open(name, "w")
        for i in xrange(1000):
            f.write("test line %d a\n" % i)
        f.close()

        self.runCmd('pipe.py', '--fnd --below --sort -t sze --cute --size 10K')

        result = self.getResultLog()
        foundSmall = False
        foundBig = False
        for line in result:
            if line.find("small") != -1:
                foundSmall = True

            if line.find("big") != -1:
                foundBig = True

        self.assertTrue(foundSmall)
        self.assertFalse(foundBig)

        self.runCmd('pipe.py', '--fnd --sort -t sze --cute --size 10K')

        result = self.getResultLog()
        foundSmall = False
        foundBig = False
        for line in result:
            if line.find("small") != -1:
                foundSmall = True

            if line.find("big") != -1:
                foundBig = True

        self.assertFalse(foundSmall)
        self.assertTrue(foundBig)

    def test_Build_Pipe_From_Arguments(self):
        self.runCmd('pipe.py', '--build FilterSourceFiles "\'.\'" False '\
                    'FilterFileType "\'txt\'" FilterFileReadLines '\
                    'FilterSelectLine "[\'test.*3.*a\', \'test.*5.*b\']" '\
                    'False FilterPrintLinePlain '\
                    'FilterSinkEndPipe')

        self.assertTrue(self.inResults('test line 3 a'))
        self.assertTrue(self.inResults('test line 5 b'))


    def test_Build_Pipe_From_Arguments_Short_Names(self):
        self.runCmd('pipe.py', '--build SourceFiles "\'.\'" False '\
                    'FileType "\'txt\'" FileReadLines '\
                    'SelectLine "[\'test.*3.*a\', \'test.*5.*b\']" '\
                    'False PrintLinePlain '\
                    'SinkEndPipe')

        self.assertTrue(self.inResults('test line 3 a'))
        self.assertTrue(self.inResults('test line 5 b'))


    def test_Find_Duplicates(self):
        self.makeTestFile("testfile3.txt", "a")
        self.runCmd('pipe.py', '--fnd --dups -t txt')

        self.assertTrue(self.inResults('Equal with hash:'))
        self.assertTrue(self.inResults('testfile1.txt'))
        self.assertFalse(self.inResults('testfile2.txt'))
        self.assertTrue(self.inResults('testfile3.txt'))


if __name__ == '__main__':
    unittest.main()
